package demo.java.lang.management;

import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;

import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.sun.management.OperatingSystemMXBean;

import demo.java.lang.ThreadDemo;
import demo.javax.management.ObjectNameDemo;

/**
 * 用于操作系统的管理接口，Java 虚拟机在此操作系统上运行。
 * 
 * Java 虚拟机具有此接口的实现类的单一实例。实现此接口的实例是一个 MXBean，可以通过调用
 * ManagementFactory.getOperatingSystemMXBean() 方法或从平台 MBeanServer 方法获得。
 * 
 * 用于在 MBeanServer 中唯一标识操作系统的 MXBean 的 ObjectName 为：
 * 
 * java.lang:type=OperatingSystem 此接口定义了几种便捷方法，可使用这些方法访问关于操作系统（Java
 * 虚拟机在其上运行）的系统属性。
 * <p>
 * CPU时间即反映CPU全速工作时完成该进程所花费的时间；
 * <p>
 * CPU时间
 * <li>= N个CPU时钟周期） / 电子脉冲时钟频率
 * <li>= N个CPU时钟周期 * 电子脉冲时钟周期 （类似于晶振产生的脉冲，而频率就是单位时间产生脉冲数量 = 1/单个脉冲时钟周期占用时间）
 * 
 */
public class SunOperatingSystemMXBeanDemo {

    static Logger logger = LoggerFactory.getLogger(SunOperatingSystemMXBeanDemo.class);

    @Test
    public void test() {
        OperatingSystemMXBean osMXBean = (com.sun.management.OperatingSystemMXBean) ManagementFactory
                .getOperatingSystemMXBean();
        ObjectNameDemo.printObjectName(osMXBean.getObjectName());
    }

    /**
     * 打印属性
     * 
     * @param os
     */
    @Test
    public void printOperatingSystemMxBean() {
        OperatingSystemMXBean os = (com.sun.management.OperatingSystemMXBean) ManagementFactory
                .getOperatingSystemMXBean();
        int mb = 1024 * 1024;
        //
        logger.info("os.getCommittedVirtualMemorySize() = {}", os.getCommittedVirtualMemorySize());
        //
        logger.info("os.getTotalSwapSpaceSize() = {}", os.getTotalSwapSpaceSize());
        // Method descriptor #2 ()J
        logger.info("os.getFreeSwapSpaceSize() = {}", os.getFreeSwapSpaceSize());
        // Method descriptor #2 ()J
        logger.info("os.getProcessCpuTime() = {}", os.getProcessCpuTime());
        // Method descriptor #2 ()J
        logger.info("可用物理内存：os.getFreePhysicalMemorySize() = {}", os.getFreePhysicalMemorySize() / mb);
        // Method descriptor #2 ()J
        logger.info("总的物理内存：os.getTotalPhysicalMemorySize() = {}", os.getTotalPhysicalMemorySize() / mb);
        // Method descriptor #2 ()J
        logger.info("os.getSystemCpuLoad() = {}", os.getSystemCpuLoad());
        // Method descriptor #1 ()D
        logger.info("os.getProcessCpuLoad() = {}", os.getProcessCpuLoad());
        // Method descriptor #1 ()D
    }

    /**
     * 计算cpu占用的逻辑是：Math.min(99F, (ProcessCpuTime-PreProcessCpuTime) /
     * ((Uptime-PreUptime) * 10000F * AvailableProcessors));
     */
    @Test
    public void cpuUsage() {
        RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();
        OperatingSystemMXBean osMXBean = (com.sun.management.OperatingSystemMXBean) ManagementFactory
                .getOperatingSystemMXBean();
        long lastCPUTime = osMXBean.getProcessCpuTime();
        long lastUpTime = runtimeMXBean.getUptime();
        for (int i = 0; i < Long.MAX_VALUE; i++) {
            if (i % 1000 == 0) {
                ThreadDemo.safeSleep(10);
                long cpuTime = osMXBean.getProcessCpuTime();
                long upTime = runtimeMXBean.getUptime();
                long elapsedCpu = cpuTime - lastCPUTime;
                long elapsedTime = upTime - lastUpTime;
                double cpuUsage = elapsedCpu / (elapsedTime);
                logger.info("current: cpuTime:{},upTime:{}, elapsed:{}/{} = {}", cpuTime, upTime, elapsedCpu,
                        elapsedTime, cpuUsage);
                lastCPUTime = cpuTime;
                lastUpTime = upTime;
            }
        }
    }
}
